import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.preprocessing import PolynomialFeatures
from sklearn.ensemble import RandomForestRegressor

# 加载数据集
file_path = r"C:\Users\HYHPlayer_MHS\Documents\WeChat Files\wxid_5fx1qyfws5wv12\FileStorage\File\2024-07\house.csv"
df = pd.read_csv(file_path, encoding='gbk')

# 删除所有缺失值
d1 = df.dropna().reset_index(drop=True)

# 分解户型
def apart_room(x):
    try:
        room = x.split('室')[0]
        return int(room)
    except:
        return None

def apart_hall(x):
    try:
        hall = x.split('厅')[0].split('室')[1]
        return int(hall)
    except:
        return None

def apart_wc(x):
    try:
        wc = x.split('卫')[0].split('厅')[1]
        return int(wc)
    except:
        return None

d1['室'] = d1['户型'].map(apart_room)
d1['厅'] = d1['户型'].map(apart_hall)
d1['卫'] = d1['户型'].map(apart_wc)

# 删除无法解析户型信息的行
d1 = d1.dropna(subset=['室', '厅', '卫'])

# 删除楼层、户型、单价
d1.drop(columns=['户型', '楼层', '单价'], inplace=True)

# 确保“建筑面积”中的值为字符串，并去除“平米”字符，然后转换为float类型
d1['建筑面积'] = d1['建筑面积'].astype(str).str.replace('平米', '').astype(float)

# 确保“总价”中的值为字符串，并去除“万元”字符，然后转换为float类型
d1['总价'] = d1['总价'].astype(str).str.replace('万元', '').astype(float)

# 编码 - 有序多分类
map1 = {'南': 5, '南北': 6, '北': 1, '西南': 10, '东西': 4, '东': 2, '东北': 8, '东南': 9, '西': 3, '西北': 7}
d1['朝向'] = d1['朝向'].map(map1)

map2 = {'毛坯': 1, '简装修': 2, '精装修': 3, '中装修': 4, '豪华装修': 5}
d1['装修'] = d1['装修'].map(map2)

map3 = {'有 ': 1, '无 ': 0}
d1['电梯'] = d1['电梯'].map(map3)

map4 = {'商品房': 6, '个人产权': 5, '商品房(免税)': 7, '普通商品房': 4, '经济适用房': 2, '房改房': 3, '限价房': 8, '房本房': 1}
d1['产权性质'] = d1['产权性质'].map(map4)

map5 = {'普通住宅': 4, '经济适用房': 3, '公寓': 1, '商住楼': 2, '酒店式公寓': 5}
d1['住宅类别'] = d1['住宅类别'].map(map5)

map6 = {'平层': 4, '开间': 2, '跃层': 5, '错层': 1, '复式': 3}
d1['建筑结构'] = d1['建筑结构'].map(map6)

map7 = {'板楼': 4, '钢混': 5, '塔板结合': 3, '平房': 6, '砖混': 1, '塔楼': 7, '砖楼': 2}
d1['建筑类别'] = d1['建筑类别'].map(map7)

map8 = {'城关': 6, '安宁': 5, '七里河': 4, '西固': 3, '榆中': 2, '永登': 1}
d1['区域'] = d1['区域'].map(map8)

# 去除“建筑年代”中的非数字字符，并转换为int类型
d1['建筑年代'] = d1['建筑年代'].astype(str).str.extract('(\d+)', expand=False).astype(int)

# 删除超过2019年的房子，年代转变为房龄
d1.drop(index=d1[d1['建筑年代'] > 2019].index, inplace=True)
d1['房龄'] = 2020 - d1['建筑年代']
d1.drop(columns=['建筑年代'], inplace=True)

# 再次删除任何包含NaN的行
d1 = d1.dropna()

# 显示处理后的数据集
print("处理后的数据集:")
print(d1.head())

# 统计分析：计算各户型的数量和平均总价
house_type_grouped_data = d1.groupby(['室', '厅', '卫']).agg(
    平均总价=('总价', 'mean'),
    数量=('总价', 'size')
).reset_index()

# 显示不同户型的统计结果
print("\n不同户型的统计结果:")
print(house_type_grouped_data)

# 可视化：绘制不同户型的平均总价
plt.figure(figsize=(12, 6))
sns.barplot(x='室', y='总价', hue='厅', data=d1, estimator='mean')
plt.title('不同户型的平均总价')
plt.xlabel('室')
plt.ylabel('平均总价（万元）')
plt.legend(title='厅')
plt.grid(True)
plt.show()

# 可视化：绘制不同户型的平均单价
plt.figure(figsize=(12, 6))
sns.barplot(x='室', y='总价', hue='卫', data=d1, estimator='mean')
plt.title('不同户型的平均总价')
plt.xlabel('室')
plt.ylabel('平均总价（万元）')
plt.legend(title='卫')
plt.grid(True)
plt.show()

# 准备训练和测试数据
X = d1.drop(columns=['总价'])
y = d1['总价']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=33)

# 多项式特征转换
poly = PolynomialFeatures(degree=2)
x_train = poly.fit_transform(X_train.values)
x_test = poly.fit_transform(X_test)

# 套索回归
la = Lasso(alpha=0.1, max_iter=100000)
la.fit(x_train, y_train)
print(f'训练集得分：{round(la.score(x_train, y_train), 2)}')
print(f'测试集得分：{round(la.score(x_test, y_test), 2)}')

# 随机森林
rf = RandomForestRegressor()
rf.fit(x_train, y_train)
print(f'训练集得分：{round(rf.score(x_train, y_train), 2)}')
print(f'测试集得分：{round(rf.score(x_test, y_test), 2)}')